package org.yzh.web.component.qiniu;

import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.processing.OperationManager;
import com.qiniu.processing.OperationStatus;
import com.qiniu.qvs.RecordManager;
import com.qiniu.qvs.StreamManager;
import com.qiniu.qvs.model.DynamicLiveRoute;
import com.qiniu.qvs.model.Stream;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.yzh.web.config.QiniuConfig;
import org.yzh.web.model.vo.QiniuDynamicUrl;
import org.yzh.web.model.vo.RecordClipsSaveResult;
import org.yzh.web.model.vo.RecordsPlayback;

/**
 * @author lsj
 * @date 2021/1/18 19:11
 */
@Component
@Slf4j
public class QiniuManager {

    private final QiniuConfig config;
    private final Auth auth;
    private final StreamManager streamManager;
    private final RecordManager recordManager;
    private final BucketManager bucketManager;
    private final OperationManager operationManager;

    public QiniuManager(QiniuConfig config) {
        this.config = config;
        this.auth = Auth.create(config.getAccessKey(), config.getSecretKey());
        this.streamManager = new StreamManager(auth);
        this.recordManager = new RecordManager(auth);
        Configuration cfg = new Configuration(Region.autoRegion());
        this.bucketManager = new BucketManager(auth, cfg);
        this.operationManager = new OperationManager(auth, cfg);
    }

    /**
     * 获取文件信息
     * @param bucket
     * @param fileName
     * @return
     */
    public FileInfo getFileInfo(String bucket, String fileName) {
        try {
            return bucketManager.stat(bucket, fileName);
        } catch (QiniuException e) {
            log.error("getFileInfo: ", e);
        }
        return null;
    }

    /**
     * 查询数据处理请求的状态
     * @param persistentId
     * @return
     */
    public OperationStatus getOperationStatus(String persistentId) {
        try {
            return operationManager.prefop(persistentId);
        } catch (QiniuException e) {
            log.error("getOperationStatus: ", e);
        }
        return null;
    }


    /**
     * 创建流
     *
     * @param streamId
     */
    public void createStream(String streamId) {
        try {
            Response response = streamManager.createStream(config.getNamespaceId(),
                new Stream(streamId, "Program Create", config.getRecordTemplateId(), null));
            if (response.isOK()) {
                log.info("createStream: body: {}", response.bodyString());
                return;
            }
            log.error("createStream: call createStream failed statusCode: {} error: {}", response.statusCode,
                response.error);
        } catch (QiniuException e) {
            Response response = e.response;
            if (response != null && response.statusCode == 614 && "stream exists".equals(response.error)) {
                log.warn("createStream: stream exists");
                return;
            }
            log.error("createStream: error ", e);
        }
    }

    /**
     * 动态获取流地址
     */
    public QiniuDynamicUrl generateDynamicUrl(String streamId) {
        try {
            Response response = streamManager.dynamicPublishPlayURL(config.getNamespaceId(), streamId,
                new DynamicLiveRoute("127.0.0.1", "127.0.0.1", 0));
            if (response.isOK()) {
                log.info("generateDynamicUrl: body {}", response.bodyString());
                return response.jsonToObject(QiniuDynamicUrl.class);
            }
            log.error("generateDynamicUrl: call dynamicPublishPlayURL failed statusCode: {} error: {}",
                response.statusCode, response.error);
        } catch (QiniuException e) {
            log.error("generateDynamicUrl: error ", e);
        }
        return new QiniuDynamicUrl();
    }

    /**
     * 录制视频回放
     *
     * @param streamId 流ID
     * @param start    开始时间
     * @param end      结束时间
     * @return 回放对象
     */
    public RecordsPlayback recordsPlayback(String streamId, int start, int end) {
        try {
            Response response = recordManager.recordsPlayback(config.getNamespaceId(), streamId, start, end);
            if (response.isOK()) {
                log.info("recordsPlayback: body {}", response.bodyString());
                return response.jsonToObject(RecordsPlayback.class);
            }
            log.error("recordsPlayback: call recordsPlayback failed statusCode: {} error: {}", response.statusCode,
                response.error);
        } catch (QiniuException e) {
            log.error("recordsPlayback: error ", e);
        }
        return new RecordsPlayback();
    }

    /**
     * 录制视频保存
     *
     * @param streamId        流ID
     * @param fileName        文件名
     * @param format          文件格式 m3u8,mp4,flv
     * @param start           开始时间
     * @param end             结束时间
     * @param notifyUrl       保存成功通知的url 不指定则不通知
     * @param deleteAfterDays 过期时间默认跟录制模板设置保持一致 30天
     */
    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start, int end,
        boolean deleteTs, String pipeline, String notifyUrl, int deleteAfterDays) {
        RecordClipsSaveResult result = new RecordClipsSaveResult();
        try {
            Response response = recordManager
                .recordClipsSaveas(config.getNamespaceId(), streamId, fileName, format, start, end, deleteTs, pipeline,
                    notifyUrl, deleteAfterDays);
            if (response.isOK()) {
                log.info("recordClipsSaveAs: body {}", response.bodyString());
                result = response.jsonToObject(RecordClipsSaveResult.class);
                result.setFileUrl(config.getBucketDomain().replaceAll("\\/$", "") + "/" + result.getFname());
                result.setCode(response.statusCode);
                result.setError(response.error);
            } else {
                log.error("recordClipsSaveAs: call recordClipsSaveAs failed statusCode: {} error: {}", response.statusCode,
                    response.error);
                result.setCode(response.statusCode);
                result.setError(response.error);
            }
        } catch (QiniuException e) {
            log.error("recordClipsSaveAs: error", e);
            result.setCode(e.response.statusCode);
            result.setError(e.response.error);
        }
        return result;
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start, int end,
        String pipeline, String notifyUrl, int deleteAfterDays) {
        return recordClipsSaveAs(streamId, fileName, format, start, end, false, pipeline, notifyUrl, deleteAfterDays);
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start, int end,
        String notifyUrl, int deleteAfterDays) {
        return recordClipsSaveAs(streamId, fileName, format, start, end, "", notifyUrl, deleteAfterDays);
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start, int end,
        String notifyUrl) {
        return recordClipsSaveAs(streamId, fileName, format, start, end, notifyUrl, 0);
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start, int end,
        int deleteAfterDays) {
        return recordClipsSaveAs(streamId, fileName, format, start, end, "", deleteAfterDays);
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String fileName, String format, int start,
        int end) {
        return recordClipsSaveAs(streamId, fileName, format, start, end, 0);
    }

    public RecordClipsSaveResult recordClipsSaveAs(String streamId, String format, int start, int end) {
        return recordClipsSaveAs(streamId, "", format, start, end);
    }

    public RecordClipsSaveResult recordClipsSaveAsMp4(String streamId, int start, int end) {
        return recordClipsSaveAsMp4(streamId, "", start, end);
    }

    public RecordClipsSaveResult recordClipsSaveAsMp4(String streamId, String fileName, int start, int end) {
        return recordClipsSaveAs(streamId, fileName + ".mp4", "mp4", start, end, config.getNotifyUrl());
    }

}
